---
title: Theming
---

import Seo from '../../../components/Seo.astro'
import Badge from '../../../components/Badge.astro'


<Seo
    seo={{
        title: 'Theming',
        description: 'Learn about theming with react-native-unistyles'
    }}
>

<Badge label="All platforms" />
<Badge label="2.0.0" />

Theming in `Unistyles` differs from other libraries as it doesn't impose any specific syntax.

**Any JavaScript object can be a Unistyles theme**.

There is also no limit to the number of themes. You can even register dozens of them, for example, if your app sells some premium ones.

Theming is optional. If you dont't register themes with [UnistylesRegistry](/reference/unistyles-registry)
the library will use an empty object by default.

### Create a theme

You can organize your themes however you want:

```tsx
const myTheme = {
    // any keys
    colors: {
        // your colors
    },
    components: {
        // any number of nesting
        button: {
            deepKey: {}
        }
    },
    utils: {
        // you can even use functions here
        hexToRGBA: () => {}
    },
    // or compute your themes with functions and spread operators
    ...premiumFeatures,
    ...getMyColors()
}
```

If you use TypeScript you need to override the library's type:

```tsx /name/
type AppThemes = {
  name: typeof myTheme
}

declare module 'react-native-unistyles' {
  export interface UnistylesThemes extends AppThemes {}
}
```

Finally, to register the theme, you need to call `UnistylesRegistry`:

```tsx /name/
import { UnistylesRegistry } from 'react-native-unistyles'
import { myTheme } from './themes'

UnistylesRegistry
    .addThemes({
        name: myTheme,
        // you can add more themes here
    })
```

Where `name` is the unique name of your theme.

:::tip
Your themes may have different shapes, but it's generally not recommended.
:::

### Select theme

If you've registered more than one theme, Unistyles won't know which one is the initial one.
At this point, you have 3 options:

- If you know the initial theme upfront, select it with `addConfig` from [UnistylesRegistry](/reference/unistyles-registry)

```tsx /initialTheme/
UnistylesRegistry
    .addThemes({
        light: myTheme,
        premium: premiumTheme
    })
    .addConfig({
        initialTheme: 'premium'
    })
```

- If you need to resolve the user-selected theme during runtime, call [useInitialTheme](/reference/use-initial-theme) before
using your first `useStyles` hook:

```tsx /useInitialTheme/
import { useInitialTheme, useStyles } from 'react-native-unistyles'

// can be read from any storage eg. MMKV/SQL/FileSystem/Appearance
const userTheme = ...

useInitialTheme(userTheme)

// useInitialTheme must be called before the first useStyles hook
// it's so fast that you can even call it in the same component!
const { styles } = useStyles(stylesheet)
```

- Use adaptive themes, as mentioned below

:::danger
Without a selected theme, Unistyles will throw an error:

"Your themes are registered, but you didn't select the initial theme"
:::

### Get the current theme

To get the current theme, you can either obtain it from the `useStyles` hook:

```tsx /theme/
const { theme } = useStyles()
```

or access it in the `createStyleSheet` function:

```tsx /theme/
const stylesheet = createStyleSheet(theme => ({
    ...
}))
```

### Get the current theme name

To get the current theme name, import `UnistylesRuntime`:

```tsx /UnistylesRuntime.themeName/
import { UnistylesRuntime } from 'react-native-unistyles'

// access the current theme name in your component
export const UserTheme = () => (
    <Text>
        Selected theme is {UnistylesRuntime.themeName}
    </Text>
)
```

### Adaptive themes

Adaptive themes allow Unistyles to automatically manage the selection of your themes based on device color scheme settings.
To enable this, you need to meet two conditions:

- register two themes with reserved names `light` and `dark`:

```tsx /light:/ /dark:/
UnistylesRegistry
    .addThemes({
        light: lightTheme,
        dark: darkTheme,
        // you may have more themes
    })
```

- Explicitly enable  `adaptiveThemes`:

```tsx /adaptiveThemes/
UnistylesRegistry
    .addThemes({
        light: lightTheme,
        dark: darkTheme,
        // you may have more themes
    })
    .addConfig({
        adaptiveThemes: true
    })
```

In order to support `adaptiveThemes` with SSR, please follow [this](/reference/server-side-rendering/#adaptive-themes-with-ssr) guide.

:::caution
You shouldn't enable adaptive themes and set initial theme at the same time. It may cause unpredictable behavior.
:::

### Toggle adaptive themes during runtime

To toggle adaptive theme support at any point, use `UnistylesRuntime`:

```tsx /UnistylesRuntime.setAdaptiveThemes.*/
import { UnistylesRuntime } from 'react-native-unistyles'

// toggle support for adaptive themes at any point
export const ToggleAdaptiveThemes = () => (
    <Button
        title="Disable adaptive themes"
        onPress={() => UnistylesRuntime.setAdaptiveThemes(false)}
    />
)
```

### Check if adaptive themes are enabled

To check if adaptive themes are enabled, again use `UnistylesRuntime`:

```tsx /UnistylesRuntime.hasAdaptiveThemes/
import { UnistylesRuntime } from 'react-native-unistyles'

// check if you've enabled adaptive themes
export const AdaptiveThemes = () => (
    <Text>
        Adaptive themes are {UnistylesRuntime.hasAdaptiveThemes ? 'enabled' : 'disabled'}
    </Text>
)
```

### Get device color scheme

Check your device color preference with `UnistylesRuntime`:

```tsx /colorScheme/
import { UnistylesRuntime } from 'react-native-unistyles'

// check the current device scheme preference
export const UserTheme = () => (
    <Text>
        My device is using the {UnistylesRuntime.colorScheme} scheme.
    </Text>
)
```

Available options are: `dark`, `light` or `unspecified` for devices that don't support color schemes.

:::caution
Unistyles will read your device settings, not user preferences. It's not compatible with the React Native `Appearance` module.
:::

If your app's theme is not changing based on device settings, please refer to the [FAQ](/reference/faq/)

### Change theme

With Unistyles 2.0, we no longer use a React Context. However, this doesn't mean you can't change the theme.
In fact, it's even easier as you don't need to re-render the entire app.
To change the theme at any time, simply call `setTheme` function:

```tsx /UnistylesRuntime.setTheme.*/
import { UnistylesRuntime } from 'react-native-unistyles'

// change the theme in any component
export const ChangeTheme = () => (
    <Button
        title="Change theme"
        onPress={() => UnistylesRuntime.setTheme('dark')}
    />
)
```

:::tip[UnistylesRuntime]
UnistylesRuntime is a powerful feature, and you can learn more about it [here](/reference/unistyles-runtime).
:::

### Update theme during runtime

<Badge label="All platforms" />
<Badge label="2.2.0" />

Unistyles allows you to update your theme during runtime. This is useful if you want to show the user interface with default colors and later alter theme based on user preferences.

If you update the currently selected theme, it will be automatically applied, and Unistyles will notify all stylesheets about the change. Otherwise, theme will be updated silently.

To update the theme during runtime, call `updateTheme` function, and return new theme object:

```tsx /UnistylesRuntime.updateTheme/
import { UnistylesRuntime } from 'react-native-unistyles'

// update the theme at any time
export const UpdateTheme = ({ selectedColors }) => (
    <Button
        title="Update theme"
        onPress={() => UnistylesRuntime.updateTheme('dark', currentTheme => ({
            ...currentTheme,
            colors: {
                ...currentTheme.colors,
                ...selectedColors
            }
        }))}
    />
)
```

### Update statusBar color during runtime

<Badge label="Android" />
<Badge label="2.6.0" />

Sometimes your app needs to dynamically change the status bar color, for example, when entering image preview or on some onboarding screens. You can easily update the color with `UnistylesRuntime` and for example the `useEffect` hook:

```tsx /statusBar.setColor/
import React, { useEffect } from 'react'
import { UnistylesRuntime, useStyles } from 'react-native-unistyles'

export const OnboardingScreen = () => {
    const { theme } = useStyles()

    useEffect(() => {
        UnistylesRuntime.statusBar.setColor(theme.colors.primary)

        return () => {
            // set default color
            UnistylesRuntime.statusBar.setColor(undefined)
        }
    }, [])

    // your onboarding JSX
    return ()
}
```
:::tip[Colors]
Unistyles supports only a few colors and hex values. Check the compability [here](#status-and-navigation-bar-colors)
:::

### Update navigationBar color during runtime

<Badge label="Android" />
<Badge label="2.6.0" />

Just as with the `statusBar`, you can do the same with the `navigationBar` and set a specified color.

```tsx /navigationBar.setColor/
import React, { useEffect } from 'react'
import { UnistylesRuntime, useStyles } from 'react-native-unistyles'

export const ImagePreview = ({ imageUri }) => {
    const { theme } = useStyles()

    useEffect(() => {
        UnistylesRuntime.navigationBar.setColor(theme.colors.black)

        return () => {
            // set default color
            UnistylesRuntime.navigationBar.setColor(undefined)
        }
    }, [])

    // your image preview JSX
    return ()
}
```
:::tip[Colors]
Unistyles supports only a few colors and hex values. Check the compability [here](#status-and-navigation-bar-colors)
:::

### Status and Navigation bar colors

Unistyles supports all 6- and 8-character hex colors with a `#` prefix, as well as some built-in colors:

red, blue, green, black, white, gray, cyan, magenta, yellow, light gray, dark gray, grey, light grey, dark grey, aqua, fuchsia, lime, maroon, navy, olive, purple, silver, and teal.

:::danger
It's not possible to set a color for a **translucent** navigation bar.

If you set an unsupported color or attempt to do so on a translucent navigation bar, Unistyles will silently fail.
:::
</Seo>
